Skip to content

Add UI that enables user to gloss tokens and add render window for ContinuousView#77

Draft
alex-rawlings-yyc wants to merge 10 commits into
mainfrom
gloss-token
Draft

Add UI that enables user to gloss tokens and add render window for ContinuousView#77
alex-rawlings-yyc wants to merge 10 commits into
mainfrom
gloss-token

Conversation

@alex-rawlings-yyc
Copy link
Copy Markdown
Contributor

@alex-rawlings-yyc alex-rawlings-yyc commented May 19, 2026

  • Add gloss input to TokenChip (word tokens only): bordered chip now stacks surface text above an editable gloss field
  • Thread glosses (Record<string, string>) and onGlossChange(tokenId, value) props down through TokenChip → PhraseBox → SegmentView → ContinuousView
  • Introduce a phrase-window around the focused index in ContinuousView to cap rendered PhraseBoxes and reduce overhead on large books
  • Replace SegmentView's onClick with onSelect(ref, tokenId?) so the clicked token id propagates up to Interlinearizer
  • Add activePhraseIndex prop to ContinuousView for external phrase jumps when a segment-view token is clicked in continuous-scroll mode
  • Update tests to cover gloss propagation, activePhraseIndex jumps, and both phrase-window boundary branches

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Per-token gloss store with live editable gloss inputs across views.
    • External phrase-focus control and direct phrase-index jumps for continuous scrolling.
  • Improvements

    • Windowed token-strip rendering for large books; improved responsiveness and scroll/focus handling.
    • Better focus preservation across mode switches and more reliable verse-change notifications.
  • Tests

    • Expanded and standardized test coverage for gloss editing, focus/scroll behavior, mode transitions, and large-book windowing.
  • Documentation

    • Clarified JSDoc for loader and memoized components.

Review Change Stack

@alex-rawlings-yyc alex-rawlings-yyc self-assigned this May 19, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 116a004f-93c4-47d4-ad68-d10e35c9cf0c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

This PR wires per-token gloss editing through TokenChip/PhraseBox/SegmentView/ContinuousView, adds external phrase focus control and windowed continuous rendering, preserves focus across mode switches, implements coordinated scrolling, and updates/extends tests to cover these behaviors.

Changes

Gloss editing and phrase focus

Layer / File(s) Summary
TokenChip gloss input support
src/components/TokenChip.tsx, src/__tests__/components/TokenChip.test.tsx
TokenChip renders a controlled gloss <input> for word tokens, forwards onFocus/onGlossChange, and updates layout; tests verify textbox presence, values, per-keystroke callbacks, and focus handling.
PhraseBox gloss wiring and interactive wrapper
src/components/PhraseBox.tsx, src/__tests__/components/PhraseBox.test.tsx
PhraseBox requires glosses/onGlossChange, forwards per-token gloss/focus handlers to TokenChip, sets tabIndex={-1} for interactive button path, and updates focused styling; tests add requiredProps/nonInteractiveProps helpers and validate gloss propagation and interactive/non-interactive branches.
SegmentView mode-specific roots and selection API
src/components/SegmentView.tsx, src/__tests__/components/SegmentView.test.tsx
SegmentView replaces onClick with onSelect(ref, tokenId?), requires glosses/onGlossChange, accepts optional focusedTokenId, and returns button for baseline-text or div with PhraseBox/TokenChip for token-chip; tests updated to assert selection and gloss flows and aria-current rendering.
ContinuousView external focus, windowing, and tests
src/components/ContinuousView.tsx, src/__tests__/components/ContinuousView.test.tsx
ContinuousView adds activePhraseIndex, requires activeVerse/onVerseChange, accepts glosses/onGlossChange and onFocusPhraseIndexChange, prefers activePhraseIndex for initial focus, window-renders phrases with PHRASE_WINDOW_HALF, coordinates external/internal jumps via refs, and standardizes/extends tests (large-book fixture, activePhraseIndex timing/regression coverage).
Interlinearizer state and coordination
src/components/Interlinearizer.tsx, src/__tests__/components/Interlinearizer.test.tsx
Interlinearizer manages shared glosses and focusedTokenId, builds wordTokens/phraseIndexByTokenId, preserves focus across mode switches, scrolls active segment into view, and wires ContinuousView/SegmentView with gloss/focus callbacks; tests assert selection, focus carryover, and gloss propagation.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SegmentView
  participant ContinuousView
  participant TokenChip
  participant Interlinearizer
  User->>SegmentView: click token
  SegmentView->>Interlinearizer: onSelect(ref, tokenId)
  Interlinearizer->>Interlinearizer: compute activePhraseIndex
  Interlinearizer->>ContinuousView: activePhraseIndex (prop)
  ContinuousView->>ContinuousView: update focusPhraseIndex / window
  ContinuousView->>Interlinearizer: onFocusPhraseIndexChange(focusIndex)
  Interlinearizer->>SegmentView: focusedTokenId (prop)
  User->>TokenChip: type gloss
  TokenChip->>Interlinearizer: onGlossChange(tokenId, value)
  Interlinearizer->>ContinuousView: glosses (prop)
  Interlinearizer->>SegmentView: glosses (prop)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • sillsdev/interlinearizer-extension#40: Main PR extends the continuous-scroll implementation introduced in PR #40 by heavily updating ContinuousView's focus/navigation model and wiring gloss-editing callbacks.

Suggested labels

🟥High

Suggested reviewers

  • imnasnainaec
  • jasonleenaylor

Poem

🐰 I nibble letters, glosses tucked in rows,
Phrases hop to focus where the daylight glows,
From strip to segment, every token shows,
Tiny inputs bloom where little knowledge grows,
Hop — edit, focus, scroll — the interlinear flows.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'Add UI that enables user to gloss tokens and add render window for ContinuousView' accurately describes the two main changes: gloss input UI for tokens and a phrase-window optimization for ContinuousView.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gloss-token

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@alex-rawlings-yyc alex-rawlings-yyc linked an issue May 19, 2026 that may be closed by this pull request
coderabbitai[bot]

This comment was marked as outdated.

alex-rawlings-yyc

This comment was marked as outdated.

@alex-rawlings-yyc

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@alex-rawlings-yyc

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@sillsdev sillsdev deleted a comment from coderabbitai Bot May 20, 2026
@sillsdev sillsdev deleted a comment from coderabbitai Bot May 20, 2026
@alex-rawlings-yyc alex-rawlings-yyc changed the title Add UI that enables user to gloss tokens Add UI that enables user to gloss tokens and add render window for ContinuousView May 20, 2026
@alex-rawlings-yyc alex-rawlings-yyc force-pushed the gloss-token branch 2 times, most recently from 46af76b to 68b2942 Compare May 20, 2026 21:48
coderabbitai[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as outdated.

@alex-rawlings-yyc alex-rawlings-yyc marked this pull request as draft May 21, 2026 16:44
- Add gloss input to TokenChip (word tokens only): bordered chip now stacks surface text above an editable gloss field
- Thread `glosses` (Record<string, string>) and `onGlossChange(tokenId, value)` props down through TokenChip → PhraseBox → SegmentView → ContinuousView
- Introduce a phrase-window around the focused index in ContinuousView to cap rendered PhraseBoxes and reduce overhead on large books
- Replace SegmentView's `onClick` with `onSelect(ref, tokenId?)` so the clicked token id propagates up to Interlinearizer
- Add `activePhraseIndex` prop to ContinuousView for external phrase jumps when a segment-view token is clicked in continuous-scroll mode
- Update tests to cover gloss propagation, `activePhraseIndex` jumps, and both phrase-window boundary branches
…nChip` type guard to ensure that `input` always has a handler; update docs
…, add coalescing nullish fallback for token chip gloss, extract names prop types for components
…tton

- Replace the `glosses`/`onGlossChange` prop-drilling pattern with a `GlossStoreProvider` context backed by `useSyncExternalStore`, so `TokenChip` reads and writes glosses directly without intermediary props passing through `PhraseBox`, `SegmentView`, `ContinuousView`, and `Interlinearizer`.
- Add a sticky "Scroll to active verse" button (using the `LocateFixed` icon) that imperatively scrolls the `aria-current` segment into view. Rename `chapterSegments` to `bookSegments` throughout.
- Extract `InertTokenChip` / `MemoizedInertTokenChip` for non-word tokens, removing the punctuation branch from `TokenChip` so it only handles words
- Convert `PhraseBox` from a `<button>` to a `<label>` so clicking anywhere on the phrase focuses the first gloss input natively
- Rename prop `onClick` → `onFocusPhrase` on `PhraseBox` to reflect the narrowed trigger (gloss-input focus only, not arbitrary clicks)
- Update `ContinuousView` and `SegmentView` to import `MemoizedInertTokenChip` and pass `onFocusPhrase` instead of `onClick`
- Update all test mocks and assertions to match the new component shapes
- `GlossStore` stored a flat string map keyed by `token.id`. `AnalysisStore`
replaces it with a `TextAnalysis`-backed store: each gloss write creates a
new approved `TokenAnalysis` + `TokenAnalysisLink`, the full analysis snapshot
is accessible via `useAnalysis`, and `onSave` propagates changes to the caller
for persistence. The store also accepts an `analysisLanguage` prop to support
non-English glosses.

- Token identity keys are migrated from token.id to token.ref throughout
(`TokenChip`, `PhraseBox`, `SegmentView`, `ContinuousView`, `Interlinearizer`,
and all corresponding tests).

- Some unneeded tests removed and some adjustments to documents made
…with select/link/edit/delete hooks

- Introduces two new UI components: TokenAnalysisPicker (a portal-based dropdown menu for choosing among multiple analyses per token) and TokenAnalysisModal (a create/edit dialog for individual analyses).
- Introduces four new AnalysisStore hooks: useGlossSelect, useGlossLink, useAnalysisEdit, and useAnalysisDelete.
- Adds useGlossWithStatus and useTokenAnalysisEntries, which surface per-token analysis state needed by the picker.
- The gloss dispatch now demotes the previous approved link to candidate rather than keeping two approved links.
- Full test coverage added for all new components and hooks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gloss a word

1 participant